package com.zhuangyuan.cloud.web.controller;

import com.zhuangyuan.cloud.core.models.view.ActionResult;
import com.zhuangyuan.cloud.data.entities.Cart;
import com.zhuangyuan.cloud.data.entities.Cate;
import com.zhuangyuan.cloud.data.entities.CateCategory;
import com.zhuangyuan.cloud.data.entities.FileRecycleBin;
import com.zhuangyuan.cloud.data.repository.sqlite.CateCategoryRepository;
import com.zhuangyuan.cloud.data.service.CartService;
import com.zhuangyuan.cloud.data.service.CateService;
import com.zhuangyuan.cloud.data.service.CategoryService;
import com.zhuangyuan.cloud.data.service.FileRecycleBinService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.core.io.ResourceLoader;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.ui.Model;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.math.BigDecimal;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * Created by 10191042 on 2019-11-21.
 */
@Controller
@RequestMapping("/cate")
@CacheConfig(cacheNames = "my-hzy-cache")
public class CateController {
    private static Logger logger = LoggerFactory.getLogger(CateController.class);
    private static SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMddHHmmssSSS");

    private static final String FILE_UPLOAD_PATH = System.getProperty("user.dir") + "/src/main/upload";
    private static final int MODE_NEW = 1;
    private static final int MODE_EDIT = 2;

    @Autowired
    private CacheManager cacheManager;
    @Autowired
    private CateService cateService;
    @Autowired
    private CategoryService categoryService;
    @Autowired
    private CateCategoryRepository cateCategoryRepository;
    @Autowired
    private ResourceLoader resourceLoader;
    @Autowired
    private FileRecycleBinService fileRecycleBinService;
    @Autowired
    private CartService cartService;

    /**
     * @see <url>https://skrymerdev.wordpress.com/2012/09/22/qr-code-generation-with-zxing/</url> create page QR code
     * @param id
     * @return
     */
    @RequestMapping("/detail/{id}")
//    @Cacheable(key = "#id")
    public ModelAndView detail(HttpServletRequest request,@PathVariable("id") String id){
        ModelAndView mv = new ModelAndView("/cate/detail");
        Cate cate = cateService.get(id);
        mv.addObject("title","Detail "+cate.getName());
        mv.addObject("cate",cate);
        mv.addObject("images",cate.getImagePaths());
        mv.addObject("countInCart",cartService.findCateCount(request.getParameter("token"),id));
        return mv;
    }

    @RequestMapping(value = {"/","","/list"})
    public ModelAndView list(){
        ModelAndView mv = new ModelAndView("/cate/list");
        List<Cate> cates = cateService.list();
        mv.addObject("cateList",cates);
        mv.addObject("title","Cate List");
        return mv;
    }

    @RequestMapping("/new")
    public ModelAndView addNew(){
        ModelAndView mv = new ModelAndView("/cate/new");

        mv.addObject("title","Add new Cate");

        return mv;
    }

    @GetMapping("/edit/{id}")
    public ModelAndView editCate(@PathVariable("id")String id){
        ModelAndView mv = new ModelAndView("/cate/edit");
        Cate cate = cateService.get(id);
        mv.addObject("title",cate.getName());
        mv.addObject("cate",cate);
        Map obj = cateCategoryRepository.findCategoryIdByCateId(id);
        if(obj != null){
            mv.addObject("category_pid",obj.get("parent_id"));
            mv.addObject("category_id",obj.get("id"));
        }
        return mv;
    }

    @GetMapping("/addmore/{id}")
    public ModelAndView addMore(@PathVariable("id")String id){
        ModelAndView mv = new ModelAndView("/cate/add_more");
        mv.addObject("title","Add more info");
        Cate cate = cateService.get(id);
        if(cate == null)
            mv.setViewName("redirect:/error");
        mv.addObject("id",id);
        mv.addObject("imagePaths",cate.getImagePaths());
        return mv;
    }

    @PostMapping("/delete")
    @Transactional(rollbackFor = Exception.class)
    @ResponseBody
    public ActionResult doDelete(HttpServletRequest request) throws Exception {
        String id = request.getParameter("id");
        ActionResult result = null;
        Cate cate = cateService.get(id);
        if(cate == null){
            result = new ActionResult("Specified cate is not exits.");
        }else{
            boolean success = cateService.delete(cate);
            String images = cate.getDetailImagePaths();
            if(StringUtils.hasText(images)){
                String[] paths = images.split(";");
                for(String p : paths){
                    File img = new File(FILE_UPLOAD_PATH + "/"+p);
                    if(img.exists()){
                        img.delete();
                    }

                }
            }
            result = new ActionResult(success);
        }
        return result;
    }

    @PostMapping("/delete_img")
    @ResponseBody
    @Transactional
    public ActionResult doDeleteImg(HttpServletRequest request){
        ActionResult result = null;
        String id = request.getParameter("id");
        String img = request.getParameter("img");
        if(!StringUtils.hasText(id) || !StringUtils.hasText(img)){
            result = new ActionResult("Data error.");
        }else{
            Cate cate = cateService.get(id);
            if(cate == null){
                result = new ActionResult("Specified cate not exists.");
            }else{
                String imgs = cate.getDetailImagePaths();
                imgs = StringUtils.hasText(imgs)?imgs:"";
                if(imgs.contains(img+";")){
                    imgs = imgs.replace(img+";","");
                }else{
                    imgs = imgs.replace(img,"");
                }
                cate.setDetailImagePaths(imgs);
                cateService.update(cate);
                FileRecycleBin frb = new FileRecycleBin();
                frb.setCateId(id);
                frb.setName(img);
                frb.setPath(FILE_UPLOAD_PATH);
                Calendar ca = Calendar.getInstance();
                ca.setTime(new Date());
                ca.add(Calendar.DAY_OF_YEAR,30);
                frb.setExpiredDate(ca.getTime());
                fileRecycleBinService.save(frb);
                result = new ActionResult(true);
            }
        }

        return result;
    }

    @PostMapping("/create")
    @Transactional(rollbackFor = Exception.class)
    @ResponseBody
    public ActionResult createNew(HttpServletRequest request) throws Exception {
        ActionResult result = null;
        String name = request.getParameter("name");
        String shortcut = request.getParameter("shortcut");
        float price = Float.valueOf(request.getParameter("price"));
        float vipPrice = Float.valueOf(request.getParameter("vipPrice"));
        String categoryId = request.getParameter("category");
        String description = request.getParameter("description");
        //validate data
        Map<String,Object> checkMap = new HashMap<>();
        checkMap.put("name",name);
        try {
            boolean exists = cateService.exists(Cate.class,checkMap);
            if(exists){
                result = new ActionResult(String.format("%s is exists.",name));
            }else{
                Cate cate = new Cate();
                cate.setName(name);
                cate.setPrice(price);
                cate.setVipPrice(vipPrice);
                cate.setShortcut(shortcut);
                cate.setDescription(description);
                cateService.add(cate);

                CateCategory cc = new CateCategory();
                cc.setCategory(categoryService.get(categoryId));
                cc.setCate(cate);
                cateCategoryRepository.save(cc);
                result = new ActionResult(true);
                result.setRedirectUrl("/cate/addmore/"+cate.getId());
            }
        } catch (Exception e) {
            e.printStackTrace();
            logger.error("check cate exists error.",e);
            result = new ActionResult(e.getMessage());
            throw e;
        }

        return result;
    }

    @PostMapping("/update")
    @Transactional(rollbackFor = Exception.class)
    @ResponseBody
    public ActionResult doUpdate(HttpServletRequest request){
        ActionResult result = null;
        String id = request.getParameter("id");
        float price = Float.valueOf(request.getParameter("price"));
        float vipPrice = Float.valueOf(request.getParameter("vipPrice"));
        String categoryId = request.getParameter("category");
        String description = request.getParameter("description");
        //validate data
        Cate cate = cateService.get(id);
        if(cate == null){
            result = new ActionResult("Specified cate not exists.");
        }else {

            try {
                if (cate.getPrice() != price)
                    cate.setPrice(price);
                if (cate.getVipPrice() != vipPrice)
                    cate.setVipPrice(vipPrice);
                cate.setDescription(description);
                cateService.update(cate);
                CateCategory cc = cateCategoryRepository.findByCateId(id);
                if (cc != null) {
                    if (!categoryId.equals(cc.getCategory().getId())) {
                        cateCategoryRepository.delete(cc);
                        CateCategory newCc = new CateCategory();
                        newCc.setCategory(categoryService.get(categoryId));
                        newCc.setCate(cate);
                        cateCategoryRepository.save(newCc);
                    }
                } else {
                    cc = new CateCategory();
                    cc.setCategory(categoryService.get(categoryId));
                    cc.setCate(cate);
                    cateCategoryRepository.save(cc);
                }
                result = new ActionResult(true);
                result.setRedirectUrl("/cate/addmore/"+cate.getId());
            } catch (Exception e) {
                e.printStackTrace();
                logger.error("check cate exists error.", e);
                result = new ActionResult(e.getMessage());
                throw e;
            }
        }



        return result;
    }

    @PostMapping("/createMore")
    @Transactional(rollbackFor = Exception.class)
    public String doCreateMore(HttpServletRequest request, @RequestParam("newImg") MultipartFile file) throws Exception {
        String id = request.getParameter("id");
        String filePath = saveUploadFile(file);
        Cate cate = cateService.get(id);
        if(cate == null){
            Files.delete(new File(FILE_UPLOAD_PATH + "\\" +filePath).toPath());
        }else{
            String paths = cate.getDetailImagePaths();
            paths = StringUtils.hasText(paths)?(paths+";"+filePath):filePath;
            cate.setDetailImagePaths(paths);
            if(!StringUtils.hasText(cate.getIconPath())){
                cate.setIconPath(paths.split(";")[0]);
            }
            try {
                cateService.update(cate);
            }catch (Exception e){
                Files.delete(new File(FILE_UPLOAD_PATH + "\\" +filePath).toPath());
                throw e;
            }
        }
        return "redirect:/cate/addmore/"+id;

    }

    @PostMapping("/add_to_cart")
    @ResponseBody
    @Transactional
    public ActionResult addToCart(HttpServletRequest request){
        ActionResult result = null;
        String cateId = request.getParameter("cate_id");
        String userToken = request.getParameter("user_token");
        String userType = "wechart";
        Cart cart = new Cart();
        cart.setCate(cateService.get(cateId));
        cart.setCount(1);
        cart.setPromotion(UUID.randomUUID().toString());
        cart.setUserId(userToken);
        cart.setUserType(userType);
        cartService.save(cart);
        result = new ActionResult(true);
        return result;
    }

    private String saveUploadFile(MultipartFile file) throws IOException {
        byte[] bytes = file.getBytes();
        String fileName = file.getOriginalFilename();
        String newName = simpleDateFormat.format(new Date()) + fileName.substring(fileName.lastIndexOf('.'),fileName.length());
        Path path = Paths.get(FILE_UPLOAD_PATH,newName);
        Files.write(path,bytes);
        return newName;
    }
}
